<script setup lang="ts">
import {
  ElAutocomplete,
  ElButton,
  ElCol,
  ElDialog,
  ElDivider,
  ElMenu,
  ElMenuItem,
  ElMessage,
  ElRow,
  ElScrollbar,
  ElTag
} from 'element-plus'
import { propTypes } from '@/utils/propTypes'
import 'element-plus/es/components/icon/style/css'
import 'element-plus/es/components/input/style/css'
import 'element-plus/es/components/button/style/css'
import 'element-plus/es/components/tag/style/css'
import 'element-plus/es/components/menu/style/css'
import 'element-plus/es/components/menu-item/style/css'
import { Search } from '@element-plus/icons-vue'
import { computed, onMounted, reactive, ref, useAttrs } from 'vue'
import type { Ref } from 'vue'

interface Menu {
  code: string
  name: string
  parent?: string
  selected?: boolean
}

type MenuKey = 'countries' | 'provinces' | 'cities' | 'districts'

interface Selections {
  // 国家
  countries: Menu[]
  // 省份
  provinces: Menu[]
  // 城市
  cities: Menu[]
  // 地区
  districts: Menu[]
}

const props = defineProps({
  data: propTypes.object.def({} as Selections),
  limit: propTypes.number.def(5),
  modelValue: propTypes.bool.def(false)
})

const emits = defineEmits(['update:modelValue', 'ok'])

const getBindValue = computed(() => {
  const attrs = useAttrs()
  return { ...attrs, ...props }
})

// 增加这个reactive以存储和管理状态
const state = reactive<{ selectedList: Menu[] }>({
  selectedList: [
    // { [parentCode: string]: code[] }
  ]
})

const countries = ref<Menu[]>([])
const provinces = ref<Menu[]>([])
const cities = ref<Menu[]>([])
const districts = ref<Menu[]>([])
const searchText = ref<string>('')
const keys = ref<string[]>(['countries', 'provinces', 'cities', 'districts'])

const records = ref<Menu[]>([])
const querySearch = (queryString: string, cb: any) => {
  const results = queryString ? records.value.filter(createFilter(queryString)) : records.value
  cb(results)
}
const createFilter = (queryString: string) => {
  return (record: Menu) => {
    return record.name.toLowerCase().indexOf(queryString.toLowerCase()) === 0
  }
}

// 深拷贝函数
function copyDeep(obj: any) {
  // 如果不是对象或者为 null，直接返回该值（递归基）
  if (typeof obj !== 'object' || obj === null) {
    return obj
  }

  // 初始化一个新数组或对象，来存放深复制的值
  let copy = Array.isArray(obj) ? [] : {}

  // 遍历对象或数组中的每个项
  for (let key in obj) {
    // 确保key是对象自身的属性而不是原型链上的
    if (obj.hasOwnProperty(key)) {
      // 递归复制每一项的值
      copy[key] = copyDeep(obj[key])
    }
  }

  return copy
}

const initChildrenData = (menuKey: MenuKey) => {
  if (menuKey === 'countries') {
    initMenuSelect(countries.value[0], 'countries')
    initMenuSelect(provinces.value[0], 'provinces')
    initMenuSelect(cities.value[0], 'cities')
  } else if (menuKey === 'provinces') {
    initMenuSelect(provinces.value[0], 'provinces')
    initMenuSelect(cities.value[0], 'cities')
  } else if (menuKey === 'cities') {
    initMenuSelect(cities.value[0], 'cities')
  }
}

const initData = () => {
  countries.value = copyDeep(props.data?.countries || [])
  initChildrenData('countries')
}

onMounted(() => {
  initData()
  records.value = copyDeep(props.data?.districts || [])
})

const handleSelect = (item: Menu) => {
  countries.value.forEach((item: Menu) => {
    item.selected = false
  })
  let results = findParent(item.code, 'districts').reverse()
  results[0].selected = true
  const copyCountries = copyDeep(countries.value)
  countries.value = []
  copyCountries.forEach((m: Menu) => {
    m.selected = m.code === item.parent
  })
  countries.value = copyCountries
  console.log(111, countries.value)
  results.push(item)
  results.forEach((item, index) => {
    item.selected = false
    handleMenuSelect(item, keys.value[index] as MenuKey, results.length - 1 === index)
  })
  countries.value.forEach((m: Menu) => {
    m.code !== item.code
  })
}

const getMenuSelectionByKey = (type: MenuKey) => {
  return {
    countries: countries,
    provinces: provinces,
    cities: cities,
    districts: districts
  }[type] as Ref<Menu[]>
}

// 全选/取消全选逻辑
function toggleSelectAll(menuKey: MenuKey, isSelected: boolean) {
  const menuSelection = getMenuSelectionByKey(menuKey)
  if (isSelected) {
    // 全部选择
    menuSelection.value.forEach((item) => {
      item.selected = true
    })
    if (menuKey === 'districts') {
      menuSelection.value.forEach((item) => {
        if (!state.selectedList.some((m: Menu) => m.code === item.code)) {
          state.selectedList.push(item)
        }
      })
    }
  } else {
    // 取消选择
    menuSelection.value.forEach((item) => {
      item.selected = false
    })
    if (menuKey === 'districts') {
      const codes = menuSelection.value.map((v) => v.code)
      codes.forEach((code) => {
        if (state.selectedList.some((m: Menu) => m.code === code)) {
          const index = state.selectedList.findIndex((m: Menu) => m.code === code)
          state.selectedList.splice(index, 1)
        }
      })
    }
  }
}

// 检查是否全选
function isAllSelected(menuKey: MenuKey) {
  const menuSelection = getMenuSelectionByKey(menuKey)
  return menuSelection.value?.every((item) => !!item.selected)
}

const setSelected = (selection: Ref<Menu[]>, bool: boolean) => {
  selection.value.forEach((item: Menu) => {
    item.selected = bool
  })
}

const handleTagClose = (item: Menu) => {
  const index = state.selectedList.findIndex((m) => m.code === item.code)
  state.selectedList.splice(index, 1)

  setSelected(countries, false)
  setSelected(provinces, false)
  setSelected(cities, false)
  setSelected(districts, false)
}

const getChildMenuKey = (type: MenuKey) => {
  return {
    countries: 'provinces',
    provinces: 'cities',
    cities: 'districts',
    districts: 'districts'
  }[type] as MenuKey
}

const initMenuSelect = (item: Menu, menuKey: MenuKey) => {
  if (menuKey === 'countries') {
    provinces.value = []
    cities.value = []
    districts.value = []
  }
  if (menuKey === 'provinces') {
    cities.value = []
    districts.value = []
  }
  if (menuKey === 'cities') {
    districts.value = []
  }

  const childKey = getChildMenuKey(menuKey)
  if (menuKey !== 'districts') {
    updateChildrenData(item, childKey)
  }
}

const handleMenuSelect = (item: Menu, menuKey: MenuKey, flag = false) => {
  if (state.selectedList.length >= props.limit) {
    ElMessage.warning('选择数量已达上限')
    return
  }

  const menuSelection = getMenuSelectionByKey(menuKey)
  if (menuKey === 'countries') {
    menuSelection.value.forEach((item) => {
      item.selected = false
    })
  }

  const index = menuSelection.value?.findIndex((m) => m.code === item.code)
  if (index !== -1) {
    // 切换选中状态
    menuSelection.value[index].selected = !menuSelection.value[index].selected

    // 更新selectedList
    const selectedIndex = state.selectedList.findIndex(
      (selectedItem) => selectedItem.code === item.code
    )

    if (menuKey === 'districts' || flag) {
      if (selectedIndex === -1 && menuSelection.value[index]?.selected) {
        state.selectedList.push(item)
      } else if (selectedIndex !== -1 && !menuSelection.value[index].selected) {
        state.selectedList.splice(selectedIndex, 1)
      }
    }
  }

  const menuIndex = keys.value.findIndex((key) => key === menuKey)
  const key = keys.value[menuIndex] as MenuKey
  if (key === 'countries') {
    // provinces
    provinces.value = props.data.provinces.filter((m: Menu) => m.parent === item.code)
    // cities
    const province = provinces.value[0]
    cities.value = props.data.cities.filter((m: Menu) => m.parent === province.code)
    // districts
    const city = cities.value[0]
    districts.value = props.data.districts.filter((m: Menu) => m.parent === city.code)
  } else if (key === 'provinces') {
    cities.value = props.data.cities.filter((m: Menu) => m.parent === item.code)
    const city = cities.value[0]
    districts.value = props.data.districts.filter((m: Menu) => m.parent === city.code)
  } else if (key === 'cities') {
    districts.value = props.data.districts.filter((m: Menu) => m.parent === item.code)
  }
}

const updateChildrenData = (item: Menu, menuKey: MenuKey) => {
  const menuSelection = getMenuSelectionByKey(menuKey)
  const dataList = props.data[menuKey].filter((m: Menu) => m.parent === item.code)
  menuSelection.value = dataList
}

function findParent(code: string, level: string) {
  let parentCode: string | undefined = ''
  let result: Menu | any = null

  switch (level) {
    case 'districts':
      // 查找地区的父级（城市）
      parentCode = props.data.districts.find((district) => district.code === code)?.parent
      result = props.data.cities.find((city) => city.code === parentCode)
      if (result) return [result, ...findParent(result.code, 'cities')]
      break
    case 'cities':
      // 查找城市的父级（省份）
      parentCode = props.data.cities.find((city) => city.code === code)?.parent
      result = props.data.provinces.find((province) => province.code === parentCode)
      if (result) return [result, ...findParent(result.code, 'provinces')]
      break
    case 'provinces':
      // 查找省份的父级（国家）
      parentCode = props.data.provinces.find((province) => province.code === code)?.parent
      result = props.data.countries.find((country) => country.code === parentCode)
      if (result) return [result] // 国家是最顶级，没有父级
      break
  }
  return [] // 如果没有找到父级，返回空数组
}

function closeDialog() {
  emits('update:modelValue', false)
}

const handleClose = () => {
  closeDialog()
}

const handleSubmit = async () => {
  // 提交逻辑处理
  console.log('已选择项：', state.selectedList)
  const result = {}
  state.selectedList.forEach((item) => {
    if (!result[item.parent!]) {
      result[item.parent!] = []
    }
    result[item.parent!].push(item.code)
  })
  console.log('result: ', result)
  emits('ok', result)
  handleClose()
}
</script>

<template>
  <ElDialog
    class="!rounded-lg !p-0"
    v-bind="getBindValue"
    destroy-on-close
    lock-scroll
    draggable
    :close-on-click-modal="false"
    :show-close="false"
  >
    <template #header="{ close }">
      <div class="flex justify-between items-center h-70px px-30px relative">
        <slot name="title">
          <div class="flex items-center">
            <div class="w-92px text-l font-bold">选择</div>
            <ElAutocomplete
              v-model="searchText"
              :fetch-suggestions="querySearch"
              clearable
              :prefix-icon="Search"
              class="search-input"
              placeholder="搜索"
              @select="handleSelect"
            >
              <template #default="{ item }">
                <div class="value">{{ item.name }}</div>
              </template>
            </ElAutocomplete>
          </div>
        </slot>
        <div
          class="h-54px flex justify-between items-center absolute top-[50%] right-15px translate-y-[-50%]"
        >
          <Icon
            class="cursor-pointer is-hover !h-54px"
            icon="vi-ep:close"
            hover-color="var(--el-color-primary)"
            color="var(--el-color-info)"
            @click="close"
          />
        </div>
      </div>
    </template>

    <div class="h-70px flex items-center px-30px">
      <span class="font-bold block"
        >已选 ({{ state.selectedList.length }}/{{ getBindValue.limit }})</span
      >
      <ElTag
        class="ml-2 !py-15px cursor-pointer"
        v-for="(item, index) in state.selectedList"
        :key="index"
        closable
        :class="{ '!ml-4': index === 0 }"
        @close="() => handleTagClose(item)"
      >
        {{ item.name }}
      </ElTag>
    </div>
    <ElDivider class="w-full !my-0 !-mb-1px" />

    <el-row class="flex">
      <el-col class="menu1 w-full" style="border-right: 1px solid var(--el-border-color)" :span="6">
        <ElScrollbar>
          <div class="h-360px">
            <el-menu class="h-fit !border-0">
              <template v-if="countries.length">
                <el-menu-item
                  v-for="item in countries"
                  :key="item.code"
                  :index="item.code"
                  :class="{ 'is-selected': item.selected }"
                  @click="() => handleMenuSelect(item, 'countries')"
                >
                  <span class="pl-10px">{{ item.name }}</span>
                </el-menu-item>
              </template>
            </el-menu>
          </div>
        </ElScrollbar>
      </el-col>

      <!-- 子菜单 -->
      <el-col class="w-full" :span="18">
        <el-row class="w-full flex">
          <el-col class="w-full" style="border-right: 1px solid var(--el-border-color)" :span="8">
            <ElScrollbar>
              <ElButton
                class="w-full"
                @click="toggleSelectAll('provinces', !isAllSelected('provinces'))"
              >
                {{ isAllSelected('provinces') ? '取消全选' : '全选' }}
              </ElButton>
              <div class="h-360px">
                <el-menu class="h-fit !border-0">
                  <el-menu-item
                    v-for="item in provinces"
                    :key="item.code"
                    :index="item.code"
                    :class="{ 'is-selected': item.selected }"
                    @click="() => handleMenuSelect(item, 'provinces')"
                  >
                    <span class="pl-10px">{{ item.name }}</span>
                  </el-menu-item>
                </el-menu>
              </div>
            </ElScrollbar>
          </el-col>
          <el-col class="w-full" style="border-right: 1px solid var(--el-border-color)" :span="8">
            <ElScrollbar>
              <ElButton class="w-full" @click="toggleSelectAll('cities', !isAllSelected('cities'))">
                {{ isAllSelected('cities') ? '取消全选' : '全选' }}
              </ElButton>
              <div class="h-360px">
                <el-menu class="h-fit !border-0">
                  <el-menu-item
                    v-for="item in cities"
                    :key="item.code"
                    :index="item.code"
                    :class="{ 'is-selected': item.selected }"
                    @click="() => handleMenuSelect(item, 'cities')"
                  >
                    <span class="pl-10px">{{ item.name }}</span>
                  </el-menu-item>
                </el-menu>
              </div>
            </ElScrollbar>
          </el-col>
          <el-col class="w-full" style="border-right: 1px solid var(--el-border-color)" :span="8">
            <ElScrollbar>
              <ElButton
                class="w-full"
                @click="toggleSelectAll('districts', !isAllSelected('districts'))"
              >
                {{ isAllSelected('districts') ? '取消全选' : '全选' }}
              </ElButton>
              <div class="h-360px">
                <el-menu class="h-fit !border-0">
                  <el-menu-item
                    v-for="item in districts"
                    :key="item.code"
                    :index="item.code"
                    :class="{ 'is-selected': item.selected }"
                    @click="() => handleMenuSelect(item, 'districts')"
                  >
                    <span class="pl-10px">{{ item.name }}</span>
                  </el-menu-item>
                </el-menu>
              </div>
            </ElScrollbar>
          </el-col>
        </el-row>
      </el-col>
    </el-row>

    <template #footer>
      <BaseButton class="w-74px" type="primary" @click="handleClose">取消</BaseButton>
      <BaseButton class="w-74px" @click="handleSubmit">确定</BaseButton>
    </template>
  </ElDialog>
</template>

<style lang="less">
.@{elNamespace}-overlay-dialog {
  display: flex;
  justify-content: center;
  align-items: center;
}

.@{elNamespace}-dialog {
  margin: 0 !important;

  &__header {
    height: 70px;
    padding: 0;
    margin-right: 0 !important;
    border-bottom: 1px solid var(--el-border-color);
  }

  &__body {
    padding: 0 !important;
  }

  &__footer {
    height: 70px;
    padding-right: 30px;
    border-top: 1px solid var(--el-border-color);
  }

  &__headerbtn {
    top: 0;
  }
}

.search-input {
  margin-left: 15px;

  .el-input__wrapper {
    border-radius: 15px !important;
  }
}

.el-menu-item.is-active {
  color: var(--el-menu-text-color);
  background-color: white;
}

.menu1 {
  .el-menu-item.is-active {
    color: var(--el-menu-active-color);
    background-color: var(--el-menu-hover-bg-color);
  }
}

.el-menu-item.is-selected {
  color: var(--el-menu-active-color);
  background-color: var(--el-menu-hover-bg-color);
}
</style>
